package com.wuyangnju.lj.simulation.master.model;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.wuyangnju.lj.simulation.common.Plan;
import com.wuyangnju.lj.simulation.master.model.snapshot.ComputionDataSnapshot;
import com.wuyangnju.lj.simulation.master.model.snapshot.PlanDataSnapshot;

public class ComputionData {
	private static final Log log = LogFactory.getLog(ComputionData.class);

	private Map<Plan, PlanData> planDatas;
	private final ReentrantReadWriteLock rwl;

	public ComputionData(List<Plan> plans) {
		planDatas = new LinkedHashMap<Plan, PlanData>();
		for (Plan plan : plans) {
			planDatas.put(plan, new PlanData());
		}
		rwl = new ReentrantReadWriteLock(true);
	}

	public long addDataItem(Plan plan, double dataItem) {
		rwl.readLock().lock();
		try {
			if (planDatas.containsKey(plan)) {
				return planDatas.get(plan).addDateItem(dataItem);
			} else {
				return -1;
			}
		} catch (Exception e) {
			log.error("add data item fail: " + plan + " " + dataItem, e);
		} finally {
			rwl.readLock().unlock();
		}
		return -2;
	}

	public void removePlan(List<Plan> planToRemove) {
		rwl.writeLock().lock();
		try {
			for (Plan planId : planToRemove) {
				if (planDatas.containsKey(planId)) {
					planDatas.remove(planId);
				}
			}
		} catch (Exception e) {
			log.error("remove plan fail: " + planToRemove, e);
		} finally {
			rwl.writeLock().unlock();
		}
	}

	public long surviveCount() {
		rwl.writeLock().lock();
		try {
			return planDatas.size();
		} catch (Exception e) {
			log.error("survive count fail", e);
		} finally {
			rwl.writeLock().unlock();
		}
		return -1;
	}

	public ComputionDataSnapshot snapshot() {
		rwl.writeLock().lock();
		try {
			Map<Plan, PlanDataSnapshot> planDatasSnapshot = new LinkedHashMap<Plan, PlanDataSnapshot>();
			for (Plan planId : planDatas.keySet()) {
				planDatasSnapshot.put(planId, planDatas.get(planId).snapshot());
			}
			return new ComputionDataSnapshot(planDatasSnapshot);
		} catch (Exception e) {
			log.error("snapshot fail", e);
		} finally {
			rwl.writeLock().unlock();
		}
		return null;
	}

	public void fixVar() {
		for (PlanData planData : planDatas.values()) {
			planData.setFixedVar();
		}
	}
}
